package book.chapter05.$5_3_2;

import java.util.concurrent.CountDownLatch;

import book.util.Constant;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

//ZooKeeper API创建节点，使用同步(sync)接口。
public class ZooKeeper_Create_API_Sync_Usage implements Watcher {

    private static CountDownLatch connectedSemaphore = new CountDownLatch(1);

    /**
     * 同步创建。
     * NOTEME:
     * 1. 不支持递归创建：无法在父节点不存在的情况下创建一个子节点
     * 2. 如果节点已经存在，创建同名节点，会抛出 NodeExistsException 异常
     * 3. zk 接口内容只支持byte[],需要进行序列化；
     * 4. 临时节点的特点：session 过程中保持有效；session 失效，节点自动移除；
     * <p>
     * 此处完成：
     * 1. 成功创建一个 /zk-test-ephemeral- 的临时节点；
     * 2. 创建一个临时顺序节点，由 ZK 自动在节点后缀加一个数字，得以区分，最终创建成功。
     * 3. 再创建一个 /zk-test-ephemeral- 的临时节点；会由于同名而中断。
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        ZooKeeper zookeeper = new ZooKeeper(Constant.CONN_STR,
                5000, //
                new ZooKeeper_Create_API_Sync_Usage());
        connectedSemaphore.await();
        String path1 = zookeeper.create("/zk-test-ephemeral-",
                "".getBytes(),
                Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL);
        System.out.println("Success create znode: " + path1);

        //本次会话中已经存在同名临时解决，就会直接抛出异常！程序终止。
        String path3 = zookeeper.create("/zk-test-ephemeral-",
                "".getBytes(),
                Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL);
        System.out.println("Success create znode: " + path3);


        String path2 = zookeeper.create("/zk-test-ephemeral-",
                "".getBytes(),
                Ids.OPEN_ACL_UNSAFE,
                CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println("Success create znode: " + path2);
    }

    public void process(WatchedEvent event) {
        if (KeeperState.SyncConnected == event.getState()) {
            connectedSemaphore.countDown();
        }
    }
}
